package com.java.al.swing;

import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.PlainDocument;

public class TextFields extends JFrame {
	private JButton
		b1 = new JButton("Get Text"),
		b2 = new JButton("Set Text");
	private JTextField
		t1 = new JTextField(30),
		t2 = new JTextField(30),
		t3 = new JTextField(30);
	private String s = "";
	private UpperCaseDocument ucd = new UpperCaseDocument();
	public TextFields(){
		t1.setDocument( ucd );
		ucd.addDocumentListener( new T1());
		b1.addActionListener( new B1());
		b2.addActionListener( new B2());
		t1.addActionListener( new T1A());
		setLayout(new FlowLayout());
		add(b1);
		add(b2);
		add(t1);
		add(t2);
		add(t3);
	}
	/**
	 * 文档监听! 只能监听文档的改变,而不能更改文档.
	 * 
	 * 观察者使用该接口注册以接收文本文档的更改通知.
	 * 
	 * Document 接口的默认实现 (AbstractDocument) 支持异步更改。
	 * 如果使用此功能（即变化是来自 Swing 事件线程之外的线程），则通过正发生变化的线程通知侦听器。
	 * 这意味着如果进行异步更新，则此接口的实现必须是线程安全的！ 
	 * 
	 * DocumentEvent 通知以 JavaBeans 事件模型为基础。
	 * 传递给侦听器的传递顺序是没有保证的，并且在对 Document 做进一步的更改之前，必须通知所有侦听器。
	 * 这意味着 DocumentListener 的实现不能更改事件源（即相关的 Document）。
	 * 
	 */
	class T1 implements DocumentListener{

		public void changedUpdate(DocumentEvent e) {}
		public void insertUpdate(DocumentEvent e) {	
			t2.setText(t1.getText());
			t3.setText("Text: " + t1.getText());
		}
		public void removeUpdate(DocumentEvent e) {	
			t2.setText(t1.getText());
		}
	}
	/**
	 * t1回车时第t3计数!
	 *
	 */
	class T1A implements ActionListener{
		private int count = 0 ;
		public void actionPerformed(ActionEvent e) {
			t3.setText("t1 Action Event " + count++);
		}
	}
	
	/**
	 * 如果选中文本不空则得到选中文本,
	 * 如果选中文本为空,则得到t1的全部文本内容.
	 *
	 */
	class B1 implements ActionListener{
		public void actionPerformed(ActionEvent e) {
			/**
			 * TextComponent
			 * public String getSelectedText()
			 * 返回此 TextComponent 中包含的选定文本。
			 * 如果选定为 null 或文档为空，则返回 null。
			 */
			if(t1.getSelectedText() == null ) 
				s = t1.getText();
			else
				s = t1.getSelectedText();
			/**
			 * public void setEditable(boolean b)
			 * 设置指定的 boolean 变量，以指示此 TextComponent 是否应该为可编辑的。
			 * 当状态更改时，将激发 PropertyChange 事件（"editable"）。
			 */
			t1.setEditable(true);
		}
	}
	
	/**
	 * 设置t1包含的PlainDocument对象的参数! 
	 *
	 */
	class B2 implements ActionListener{
		public void actionPerformed(ActionEvent e) {
			ucd.setUpperCase(false);
			t1.setText("Inserted by BUtton 2: " + s);
			ucd.setUpperCase(true);
		}
	}
	class UpperCaseDocument extends PlainDocument{
		private boolean upperCase = true;
		public void setUpperCase(boolean flag){
			upperCase = flag;
		}
		public void insertString(int offset, String str, AttributeSet attSet) throws BadLocationException{
			if(upperCase) str = str.toUpperCase();
			super.insertString(offset, str, attSet);
		}
	}
	public static void main(String[] args) {
		SwingConsole.run(new TextFields(), 375,200);
	}

}

